package socket.socket;

import socket.modle.ConnectedCallback;
import socket.util.SLog;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
import java.util.ArrayList;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.logging.Logger;

public class ClientSocketProxy {
    Logger log = Logger.getLogger("SocketServerUtil");
    private DataOutputStream dataOutputStream; // socket的输出流
    private DataInputStream dataInputStream; // socket的输入流

    private Socket socket;
    private int port;
    private String msgInfo;
    public String socketKey;
    private ConnectedCallback callback;
    ConcurrentLinkedQueue<byte[]> sendDataQueue = new ConcurrentLinkedQueue<>();
    public ClientSocketProxy(Socket socket, ConnectedCallback callback){
        this.callback = callback;
        this.socket = socket;
        port = socket.getPort();
        socketKey = socket.getInetAddress().toString()+","+port;
        msgInfo = socket.getInetAddress()+ "，远程端口=" + socket.getPort() + ",本地端口=" + socket.getLocalPort();
        try {
            dataOutputStream = new DataOutputStream(socket.getOutputStream());
            dataInputStream = new DataInputStream(socket.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void start(){
        Thread thread = new Thread(new ReceiverRunnable(socket));
        thread.setPriority(10);
        thread.start();
        Thread sendT = new Thread(new SendRunable());
        sendT.setPriority(9);
        sendT.start();
    }

    public void notifyConnectState(){
        callback.onConnectedStatusChange(socketKey,socket != null, null, "连接:" + msgInfo);
    }

    public void sendData(final byte[] data) {
        if (socket != null) {
            sendDataQueue.add(data);
        }
    }
    public void destroy(){
        try {
            dataInputStream.close();
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        try {
            dataOutputStream.close();
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        try {
            socket.close();
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        socket = null;
        sendDataQueue.clear();
        notifyConnectState();
    }

    private class ReceiverRunnable implements Runnable {

        Socket socket;

        ReceiverRunnable(Socket socket) {
            this.socket = socket;
        }

        @Override
        public void run() {
            try {
                while (socket != null && socket.isConnected() && !socket.isClosed()) {
                    callback.onReceive(socketKey,dataInputStream);

                    try {
                        Thread.sleep(10);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                SLog.getInstance().e_s("disconnect receiver runnable 端口 " + port);
            } catch (Exception e) {
                e.printStackTrace();
                try {
                    socket.close();
                } catch (Exception e1) {
                    e1.printStackTrace();
                }
            }
        }
    }

    private class SendRunable implements Runnable {

        @Override
        public void run() {
            while (socket != null) {
                try {
                    if (sendDataQueue.size() > 0) {
                        int readSize = Math.min(15, sendDataQueue.size());
                        ArrayList<byte[]> getbytes = new ArrayList<>(readSize);
                        int len = 0;
                        for(int i = 0; i<readSize;i++){
                            byte[] bs = sendDataQueue.poll();
                            len += bs.length;
                            getbytes.add(bs);
                        }
                        byte[] data = new byte[len];
                        int index = 0;
                        for(byte[] s: getbytes){
                            System.arraycopy(s, 0, data, index, s.length);
                            index+=s.length;
                        }
                        try {
                            dataOutputStream.write(data);
                            dataOutputStream.flush();
                        } catch (IOException e) {
                            e.printStackTrace();
                            destroy();
                        }
                  //      System.out.println(System.currentTimeMillis()+"sendDataQueue  消费后:"+sendDataQueue.size());
                    }
                    Thread.sleep(100);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }
    }
}
